public without sharing class ContractSendProductController {

    public String dataJson {get; set;}
    public String msg {get;private set;}
    public Boolean isErr {get; private set;}//错误
    public Boolean isSuccess {get; private set;}//是否保存成功
    public String backId {get; private set;}

    public String installJson {get; set;} //选择的合同明细
    public String saveJson {get;set;}

    public class ControllerException extends Exception {}
    private  Map<String,DataUtil.SObjectBean> stageObjectMap;

    public   InstallationApply__c ia {get ; private set;} 
    private ContractProduct__c selectedcp;
    public Boolean isInstall {get; private set;}

    public Boolean isReturnInstall {get; private set;}
    public Boolean isDoubleRelated {get; private set;}//是否双联机;
    public Boolean isApproval {get; set;}
    public Boolean canchangeTeriminal {get;private set;}
    public Boolean canchageEnterway {get;private set;}

    public String  DoubleRelatedConst = '双机联机';


    public ContractSendProductController() {
        canchageEnterway = true;
        //backId = System.currentPageReference().getParameters().get('id');
        backId = System.currentPageReference().getParameters().get('id');
        stageObjectMap = new Map<String,DataUtil.SObjectBean>();
        ia = new InstallationApply__c();

        selectedcp = new ContractProduct__c();
        isInstall = Id.valueOf(backId).getSobjectType() == InstallationApply__c.SobjectType;
        isReturnInstall = true;

    }



    private void setErr(String message){
        isErr  =true;
        throw new ControllerException(message);
    }

    public void editInstallApply(){
        if(isInstall){

            try{

                Map<String,Object> dataMap = new Map<String,Object>();
                ia = [select Id,Status__c,ContractEquipment__r.EnterWay__c ,FuselageNumber__c,ActualDepotTime__c ,
                SalesConfirmInstallationTime1__c ,Hospital__c,FromDeliveryRequisition__c ,InstallationType__c ,Contract__r.Account__r.RecordType.DeveloperName 
                from InstallationApply__c where Id=:backId];
                
                if(ia.ActualDepotTime__c == null || ia.FuselageNumber__c ==null ) throw new DmlException('请联系物流填写"物流实际发货时间"和"机身号"。') ;

                if(ia.Status__c == '已批准' || ia.Status__c == '审批中')throw new DmlException('安装申请'+ia.Status__c+'无需再确认!');

                canchangeTeriminal =ia.Contract__r.Account__r.RecordType.DeveloperName  != 'TerminalCustomer';
                isInstall=true ;
                isReturnInstall = !ia.FromDeliveryRequisition__c ;
                isDoubleRelated = ia.InstallationType__c == DoubleRelatedConst;


                
                canchageEnterway = ia.ContractEquipment__r.EnterWay__c == null ;
                     //字段
                 Map<String,Set<String>> fieldsmap = getFields();
                 //字段详情
                 Map<String, List<DataUtil.FieldBean>> fbMap = DataUtil.getFieldsBean(fieldsmap,stageObjectMap);
                Map<String,List<DataUtil.FieldBean>> fields = DataUtil.setFieldsValue(fbMap,DataUtil.getBaseInfo(fbMap,stageObjectMap) );
            
                dataMap.put('base',fields);

                dataMap.put('baseObject',DataUtil.getBaseObjectMap(stageObjectMap)); 
                dataJson = EncodingUtil.urlEncode(JSON.serialize(dataMap), 'UTF-8');

            }catch(Exception e ){

                isErr = true;
                ApexPages.addMessage( new ApexPages.Message(ApexPages.Severity.ERROR ,e.getMessage()));
            }
           

        }else{

            try {
                //Contract__c con = [select Id , Status__c,Account__r.RecordType.DeveloperName  from Contract__c where Id=:backId   ];
               // if(con.Status__c != 'OA审批中' && con.Status__c != '已推送OA' && con.Status__c != '已生效')throw new DmlException('不能在合同的'+con.Status__c +'阶段发起后端实施流程!');
               // canchangeTeriminal = con.Account__r.RecordType.DeveloperName  != 'TerminalCustomer';

                canchangeTeriminal = true ;

                List<Object> tmp = new List<Object>();
                Decimal t = 0;
                for(ContractProduct__c cp : [select Id,Name,CoopType__c,Quantity__c,ApplicationQuantity__c,Contract__r.ContractNumber__c  , DeliveryQuantity__c,Contract__r.Status__c,SalesPrice__c,
                Product__r.InstrumentType__c ,Opportunity__r.Account.RecordType.DeveloperName,Opportunity__r.Account.System__c 
                from ContractProduct__c where Opportunity__c =: backId order by CoopType__c,Name  ] ){

                    Map<String,Object> d = new Map<String,Object>();
                    d.put('Name', cp.Name);
                    d.put('Quantity__c', cp.Quantity__c);
                    d.put('ApplicationQuantity__c', cp.ApplicationQuantity__c);
                    d.put('DeliveryQuantity__c', cp.DeliveryQuantity__c);
                    d.put('Contract', cp.Contract__r.ContractNumber__c == null ? '' : cp.Contract__r.ContractNumber__c +'('+cp.Contract__r.Status__c +')');
                    d.put('Small', cp.Product__r.InstrumentType__c == '非维保仪器' ? '是' : '否' );
                    d.put('SalesPrice__c', cp.SalesPrice__c == null ? '' : cp.SalesPrice__c+'');
                    String type = cp.CoopType__c == '投放' ? '投放(材料/其他出库)' : '销售(仪器销售合同出库)';

                    if(cp.DeliveryQuantity__c != null )t+= cp.DeliveryQuantity__c;
                    if( cp.Contract__r.Status__c != '已生效' )type = '借出';

                    d.put('CoopType__c', type );
                    tmp.add(d);

                }
                if(tmp.isEmpty()) throw new DmlException('请先添加合作产品明细!');
                if(t == 0 )throw new DmlException('请先点击[无销售合同]或者[新建合同],待无销售合同申请批准或者相关合同仪器明细的合同OA归档后方可进行发货!');
                
                dataJson = EncodingUtil.urlEncode(JSON.serialize(tmp), 'UTF-8');


            }
            catch (Exception e) {
                isErr = true;
                ApexPages.addMessage( new ApexPages.Message(ApexPages.Severity.ERROR ,e.getMessage()));
            }
            
             

        }
        

    }

    //新建安装申请
    public void init(){

        try {

            if(backId == null )setErr('打开页面错误!');
            Map<String,Object> dataMap = new Map<String,Object>();
            dataMap.put('search', getDetails());
           
            System.debug('ContractSendProductController==>'+dataMap);

            dataJson = EncodingUtil.urlEncode(JSON.serialize(dataMap), 'UTF-8');
            
        }
        catch (Exception e) {
            isErr = true ; 
            ApexPages.addMessage( new ApexPages.Message(ApexPages.Severity.ERROR ,e.getMessage()));
        }
        
       

    }
   

    
    public void createInstall(){


        SavePoint sp = Database.setSavepoint();
        Map<String,Object> dataMap = new Map<String,Object>();
        try {


            Opportunity opp = [select Id , Account.RecordType.DeveloperName,AccountId  from Opportunity where Id=:backId   ];
           
            String spAcc = opp.Account.RecordType.DeveloperName == 'Dealer' ?  opp.AccountId  : null ;
            
            String accId = opp.Account.RecordType.DeveloperName == 'Dealer'  ? null : opp.AccountId ;
             
             List<Dealer__c>dl = [select Id , RelatedCustomers__c,Name  from Dealer__c where RelatedCustomers__c = :spAcc ];
             ia.NEWDealer__c = dl.size() > 0 ?dl[0].Id : null;

                // InstallationApply__c ia ;
             //关联合同
             //ia.Contract__c = con.Id;

             ///带入医院
            Map<String,Object> installMap = (Map<String,Object>) JSON.deserializeUntyped(EncodingUtil.urlDecode(installJson, 'UTF-8'));

            Boolean isReturn = Boolean.valueOf(installMap.get('isReturn'));
           
            //客户信息
            //Account hospital = [select Id , Name from Account where Id=:  ];
            ContractProduct__c cp  = new ContractProduct__c();

            Account hospital = new Account();
            String installAccId  = String.valueOf(installMap.get('installAccId'));
            accId = String.isBlank(installAccId) ? accId : installAccId;
            if( String.isBlank(accId) == false){
                hospital = [select Id, Name,Province__r.Name,Province__c,City__c,City__r.Name , District__c,District__r.Name  from Account where Id =:accId ];
            }
            

            Equipment__c eq  = new Equipment__c();
            if(isReturn){

                    //供货方
                cp = [select Id,Name,Product__c ,EnterWay__c,Product__r.Name ,Contract__c,Contract__r.Account__c,

                Contract__r.Maccura__c,Contract__r.Account__r.RecordType.DeveloperName

                from ContractProduct__c where Id=:String.valueOf(installMap.get('cpId')) ] ;
              
                selectedcp = cp;

                canchageEnterway = cp.EnterWay__c == null ;

                ia.ContractEquipment__c = cp.Id;
                
             //退货的仪器 仪器信息 保修条款
                eq = [select Id ,Name ,IMEINumber__c  from Equipment__c where  Id=: String.valueOf(installMap.get('returnEquipId')) ];


            }
            


            
            //ia.InstallationType__c = '同机身号仪器更换客户';
           //   ia.IMEINumber__c = eq.IMEINumber__c;
                //查找经销商
          

            //insert ia;


             //字段
             Map<String,Set<String>> fieldsmap = getFields();
             //字段详情
             Map<String, List<DataUtil.FieldBean>> fbMap = DataUtil.getFieldsBean(fieldsmap,stageObjectMap);
            
            //字段赋值
             Map<String,List<DataUtil.FieldBean>> fields = DataUtil.setFieldsValue(fbMap,DataUtil.getBaseInfo(fbMap,stageObjectMap) );

             for (DataUtil.FieldBean fb   :  fields.get('InstallationApply__c')) {
                Map<String,Object> vMap  = new Map<String,Object>();
                if(fb.name == 'Hospital__c'){

                    vMap.put('Id', hospital.Id );
                    vMap.put('Name', hospital.Name );
                    fb.value = vMap;
                }
                if(fb.name == 'ReturnedMachine__c'){

                    vMap.put('Id', eq.Id );
                    vMap.put('Name', eq.Name );
                    fb.value = vMap;
                }
                if(fb.name == 'Instrument__c'){

                    vMap.put('Id', cp.Product__c  );
                    vMap.put('Name', cp.Product__r.Name );
                    fb.value = vMap;
                }
                if(fb.name == 'NEWDealer__c' && dl.size() > 0 ){
                    vMap.put('Id', dl[0].Id  );
                    vMap.put('Name', dl[0].Name );
                    fb.value = vMap;
                }

                if(fb.name == 'InstallationType__c')fb.value = isReturn ? '同机身号仪器更换客户' : DoubleRelatedConst ;

                if(fb.name == 'FuselageNumber__c')fb.value = eq.IMEINumber__c;
                if(fb.name == 'ApplicationTraining__c')fb.value = '现场培训';
                if(fb.name == 'Period__c')fb.value = '一年/次';
                if(fb.name == 'EquipmentCheck__c')fb.value = '有偿';
                if(fb.name == 'CheckPeriod__c')fb.value = '一年/次';
                if(fb.name == 'RapidWear__c')fb.value = '自行购买';
                if(fb.name == 'CommonAccessories__c') fb.value = '自行购买';
                if(fb.name == 'EquipmentCheckGoods__c') fb.value = '自行购买';
                if(fb.name =='EnterWay__c' )fb.value = cp.EnterWay__c;

                if(fb.name == 'Instrument__c' && !isReturn ){
                        Product__c p =  [select Id,Name  from Product__c where NCcode__c = '130020200176'] ;
                        vMap.put('Id', p.Id );
                        vMap.put('Name', p.Name );
                        fb.value = vMap;
                    }

             }



             for (DataUtil.FieldBean fb   :  fields.get('Account')) {
                Map<String,Object> vMap  = new Map<String,Object>();
                if(fb.name == 'Province__c'){

                    vMap.put('Id', hospital.Province__c );
                    vMap.put('Name', hospital.Province__r.Name );
                    fb.value = vMap;
                }
                if(fb.name == 'City__c'){

                    vMap.put('Id',hospital.City__c );
                    vMap.put('Name', hospital.City__r.Name );
                    fb.value = vMap;
                }
                if(fb.name == 'District__c'){

                    vMap.put('Id', hospital.District__c  );
                    vMap.put('Name', hospital.District__r.Name  );
                    fb.value = vMap;
                }

            }
                         
            dataMap.put('base',fields);
            dataMap.put('canchageEnterway', canchageEnterway);
            dataMap.put('baseObject',DataUtil.getBaseObjectMap(stageObjectMap)); 
            
        }
        catch (Exception e) {
            Database.rollback(sp);
            ia.Id = null;
            dataMap.put('msg', '生成安装申请失败:'+e.getMessage());
        }
        
          dataJson = EncodingUtil.urlEncode(JSON.serialize(dataMap), 'UTF-8');
         System.debug('ContractSendProductController==>'+dataMap);

    }


    public Map<String,Set<String>>  getFields(){
        Map<String,Set<String>> fieldsMap  = new  Map<String,Set<String>>();
        
            DataUtil.SObjectBean sb = new DataUtil.SObjectBean();

            sb.title ='新建安装申请';
            sb.objname = 'InstallationApply__c';
            sb.stype = DataUtil.getSObjectType('InstallationApply__c');
            sb.type = 'base';
            sb.idvalue = ia.Id;
            sb.condition = ' where Id =\''+ia.Id+'\'';
            stageObjectMap.put('InstallationApply__c',sb );
            //安装类型 安装仪器 Supplier__c
            Set<String>  fields = new Set<String>{'Hospital__c','HospitalContact__c','InstallationType__c',

           'EquipmentType__c','Instrument__c','FuselageNumber__c','NEWDealer__c','EnterWay__c',
           'SupplementOrNot__c','RelatedWorkOrder__c','ActualDepotTime__c',
            'ReturnedMachine__c','InstallLocation__c','InstallEstiDate__c','OpponentDept__c','OpponentSpecialTeam__c',
            'InstallationMethod__c','Remarks__c','UPS__c','Drain__c','UPSPower__c','OutletDiameter__c','DistanceBetweenPowerHost__c',
            'DistanceBetweenDrainEngine__c','SiteArea__c','AirConditioner__c','TableSize__c','Dehumidifiers__c',
            'WaterSupplyCapacity__c','WaterMachine__c','IsConnectLIS__c','DistanceBetweenWaterMainEngine__c',
            'LISBrand__c','WarrantyPeriod__c','Warranty__c','ResponseHours__c','ChargingStandard__c','ApplicationTraining__c',
            'Period__c','EquipmentCheck__c','CheckPeriod__c','EquipmentCheckGoods__c','RapidWear__c','CommonAccessories__c',
            'SpecialRequirement__c','LaboratoryFloor__c','RequestArrivalDate__c','Elevator__c','ContactTelephone__c','ElevatorLoad__c',
            'ReceivingDepartment__c','ElevatorSize__c','ShippingAddress__c','StaircaseWidth__c','TimeReceipt__c',
            'MaximumCornerWidth__c','SiteAssistConsignee__c','SmallSteps__c','DoorwaySize__c','StepNo__c','RequestReceive__c',
            'TransportChannel__c','SceneTakeDelivery__c','IntoCityTime__c','Reagents__c','LimitPeriod__c','UnloadingPoint__c','NeedTraining__c'
            };

         
            fieldsMap.put('InstallationApply__c', fields);

            DataUtil.SObjectBean accountSb  = new DataUtil.SObjectBean();
            accountSb.title ='客户信息';
            accountSb.objname = 'Account';
            accountSb.stype = DataUtil.getSObjectType('Account');
            accountSb.type = 'base';
            accountSb.idvalue = ia.Hospital__c;
            accountSb.condition = ' where Id =\''+ia.Id+'\'';
            stageObjectMap.put('Account',accountSb );

            Set<String> accountFields = new Set<String>{
                'Province__c','City__c' ,'District__c'
            };

            fieldsMap.put('Account',accountFields );

        
        return fieldsMap;
    }

    public void setNil(){
        dataJson = '{}';
        installJson = '{}';
        saveJson = '{}';
    }

    public void save(){

        msg = '';
        Map<String,Object>saveMap = (Map<String,Object>) JSON.deserializeUntyped(EncodingUtil.urlDecode(saveJson, 'UTF-8'));
        Map<String,Set<String>> fieldsMap = getFields();
        Map<String,DataUtil.FieldBean> fbeanMap = DataUtil.getFieldsInfo(InstallationApply__c.SObjecttype,fieldsMap.get('InstallationApply__c'));
        Map<String,DataUtil.FieldBean> accfbeanMap = DataUtil.getFieldsInfo(Account.SObjecttype,fieldsMap.get('Account'));
        Account acc = new Account();

        for(String objname : saveMap.keySet()){
            Map<String,Object> obj = (Map<String,Object>) saveMap.get(objname);
            for (String field :  obj.keySet()) {

                if(obj.get(field) == null || DataUtil.getStringValue(obj.get(field)) == '') continue;

                if(objname == 'InstallationApply__c' && fbeanMap.containsKey(field) )ia.put(field, DataUtil.dataHandler(obj.get(field),fbeanMap.get(field).type.toUpperCase() ));

                if(objname == 'Account' && accfbeanMap.containsKey(field) )acc.put(field, DataUtil.dataHandler(obj.get(field),accfbeanMap.get(field).type.toUpperCase() ));
            }
            
        }
        System.debug('ContractSendProductController==>'+ia );
        acc.Id = ia.Hospital__c ;
        SavePoint sp = Database.setSavepoint();

        try {

            List<String> esets = new List<String>();
            if(ia.FuselageNumber__c != null ){

                for(String s : ia.FuselageNumber__c.split(',',-1) ) {

                    if(String.isNotBlank(s))esets.add(s.trim());
                }

            }

            System.debug('xx'+ia.RelatedWorkOrder__c);
            System.debug([select Id  from  WorkOrder__c 
                    where Account__c =:ia.Hospital__c and ManufactureInfo__c =:ia.Instrument__c  and Id !=: ia.RelatedWorkOrder__c 
                    and IMEINumber__c in:esets and Status__c = '完成'  and RecordType.DeveloperName in ('InstallationOrder','NonAgentInstallationOrder')] );
            System.debug('xx=>'+ia.SupplementOrNot__c);
            

            if( ia.SupplementOrNot__c != '是'  && [select count() from  WorkOrder__c 
                    where Account__c =:ia.Hospital__c and ManufactureInfo__c =:ia.Instrument__c  and Id !=: ia.RelatedWorkOrder__c 
                    and IMEINumber__c in:esets and Status__c = '完成'  and RecordType.DeveloperName in ('InstallationOrder','NonAgentInstallationOrder') ]>0)throw new DmlException('已经存在相同客户相同型号相同机身号的安装工单,请确认是否为补单。若确定补单，请将“是否补单”选择为“是”并选择“相关工单”');
                
                //InstallationApply__c ia;

            if(isInstall) {

                if(ia.Id  == null ) ia.Id = backId ;

                
                
                if(ia.RelatedWorkOrder__c != null && [select count() from InstallationApply__c where RelatedWorkOrder__c =: ia.RelatedWorkOrder__c and Id !=: ia.Id  ]>0) throw new DmlException('该工单已经被其他安装申请关联了不能重复关联!');
                if(ia.SalesConfirmInstallationTime1__c == null )ia.SalesConfirmInstallationTime1__c = System.today();



                update ia ;



            }else{

                if(ia.InstallationType__c !=  DoubleRelatedConst ){
                    //生成前置发货单据
                    InstrumentDeliveryApplication__c inda = new InstrumentDeliveryApplication__c();
                    inda.RecordTypeId = Utils.getRecordTypeIdByDevNameAndObjName('VirtualDeliveryRequest', 'InstrumentDeliveryApplication__c');
                    List<Dealer__c > dlist = [select Id,RelatedCustomers__c  from Dealer__c where Id=:ia.NEWDealer__c ];
                    if(dlist.size() > 0 )inda.InvoicingCustomers__c = dlist[0].RelatedCustomers__c ;
                    inda.ReceivingCustomer__c = ia.Hospital__c;
                    inda.DeliveryRelatedContracts__c = selectedcp.Contract__c;
                    inda.NotifiedAssistantTime__c = System.today(); 
                    insert inda;

                    InstrumentDeliverynDetails__c idd = new InstrumentDeliverynDetails__c();
                    idd.DeliveryInstrument__c =  selectedcp.Id;
                    idd.Number__c = 1;
                    idd.FuselageNumber__c =  ia.FuselageNumber__c;
                    idd.ReturnToMainTable__c = inda.Id;

                    
                    insert idd;
                     ia.InstallInstruments__c = idd.Id;
                }
                
                
                ia.SalesConfirmInstallationTime1__c = System.today();
                insert ia;




            }

            update acc;
            
            if(isApproval){

                Approval.ProcessSubmitRequest req1 = new Approval.ProcessSubmitRequest(); 

                req1.setObjectId(ia.id);
                Approval.ProcessResult result = Approval.process(req1);  
                if( result != null && result.getErrors() != null &&  result.getErrors().size()> 0 ) {

                    throw  new DmlException(result.getErrors()[0].getMessage());
                }
            }

            backId = ia.Id;
            isSuccess = true;
            msg = '保存成功!';

        }catch (Exception e) {
            ia.Id = null;
            Database.rollback(sp);
            msg = '保存失败:'+e.getMessage()+e.getStackTraceString();

        }
        

    }


    //获取 已经退货的合同仪器明细
    public List<ProductBean> getDetails(){
        List<ProductBean>tmp = new List<ProductBean>();
        for(ContractProduct__c cp : [select Id ,Product__c ,Product__r.Model__c,Product__r.ProductName__c,Product__r.Brand__c,Product__r.Spec__c,Product__r.NCCode__c,
        Contract__r.Account__r.RecordType.DeveloperName,Contract__r.Account__c,Contract__r.Account__r.Name ,
         Measure_Calculate_Product__r.Measure_Calculate__r.Name,QuoteProduct__r.Quote__r.Name,InstrumentPolicy__r.InstrumentPolicy__r.Name
         from ContractProduct__c where Opportunity__c =: backId  and DeliveryQuantity__c > 0   ]){
            tmp.add(new ProductBean(cp));

        }
        return tmp;

    }


    public class ProductBean{

        public String cpId;
        public String productName;
        public String productId;
        public String brand;
        public String nccode;
        public String spec;
        public String origin;
        public String installAccId;
        public String installAccName;
        public Boolean isTerminal ;

        public ProductBean(ContractProduct__c cp ){
            cpId = cp.Id;
            productName = cp.Product__r.ProductName__c;
            productId = cp.Product__c;
            brand = cp.Product__r.Brand__c;
            nccode = cp.Product__r.NCCode__c;
            spec = cp.Product__r.Spec__c ;
            if(spec == null ) spec = cp.Product__r.Model__c;
            if( cp.Measure_Calculate_Product__r.Measure_Calculate__r.Name != null )origin = cp.Measure_Calculate_Product__r.Measure_Calculate__r.Name;
            if( cp.InstrumentPolicy__r.InstrumentPolicy__r.Name != null )origin = cp.InstrumentPolicy__r.InstrumentPolicy__r.Name;
            if( cp.QuoteProduct__r.Quote__r.Name != null )origin = cp.QuoteProduct__r.Quote__r.Name;
            isTerminal = cp.Contract__r.Account__r.RecordType.DeveloperName == 'TerminalCustomer';
            if( isTerminal) installAccId = cp.Contract__r.Account__c;
            if(isTerminal) installAccName = cp.Contract__r.Account__r.Name;

        }

    }


}